package com.vcredit.creditcat.manager;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.vcredit.bird.api.INetCreditService;
import com.vcredit.bird.enumtype.NetCreditQufierEnum;
import com.vcredit.bird.service.base.BirdResponse;
import com.vcredit.bird.vo.netcredit.BankcardInitParam;
import com.vcredit.bird.vo.netcredit.BankcardSubmitParam;
import com.vcredit.bird.vo.netcredit.CreditCardResultParam;
import com.vcredit.bird.vo.netcredit.CreditLoanResultParam;
import com.vcredit.bird.vo.netcredit.CreditRecordResultParam;
import com.vcredit.bird.vo.netcredit.EmailParam;
import com.vcredit.bird.vo.netcredit.LoginParam;
import com.vcredit.bird.vo.netcredit.Question;
import com.vcredit.bird.vo.netcredit.QuestionFirstStepParam;
import com.vcredit.bird.vo.netcredit.QuestionSecondParam;
import com.vcredit.bird.vo.netcredit.RegisterFirstStepParam;
import com.vcredit.bird.vo.netcredit.RegisterSecondStepParam;
import com.vcredit.bird.vo.netcredit.RegisterThirdStepParam;
import com.vcredit.bird.vo.netcredit.ReportAllParam;
import com.vcredit.bird.vo.netcredit.ReportParam;
import com.vcredit.creditcat.api.IAuthNetCreditManager;
import com.vcredit.creditcat.dto.BankcardInitDto;
import com.vcredit.creditcat.dto.BankcardInitResult;
import com.vcredit.creditcat.dto.BankcardSubmitDto;
import com.vcredit.creditcat.dto.BaseInfoDto;
import com.vcredit.creditcat.dto.CardRecordDto;
import com.vcredit.creditcat.dto.CardRecordsDetail;
import com.vcredit.creditcat.dto.CardSerialDto;
import com.vcredit.creditcat.dto.CreditLoginDto;
import com.vcredit.creditcat.dto.InitDto;
import com.vcredit.creditcat.dto.LoanRecordDetailDto;
import com.vcredit.creditcat.dto.LoanRecordDto;
import com.vcredit.creditcat.dto.LoanRecordsDto;
import com.vcredit.creditcat.dto.NetCreditBaseResultDto;
import com.vcredit.creditcat.dto.QueryRecordDto;
import com.vcredit.creditcat.dto.QueryRecordsDetail;
import com.vcredit.creditcat.dto.QuerySerialDto;
import com.vcredit.creditcat.dto.QuestionFirstStepDto;
import com.vcredit.creditcat.dto.QuestionSecondDto;
import com.vcredit.creditcat.dto.RegisterFirstStepDto;
import com.vcredit.creditcat.dto.RegisterSecondStepDto;
import com.vcredit.creditcat.dto.RegisterThirdStepDto;
import com.vcredit.creditcat.dto.ReportDto;
import com.vcredit.creditcat.dto.ReportResponseDto;
import com.vcredit.creditcat.enumtype.AuthCreditStatusEnum;
import com.vcredit.creditcat.enumtype.AuthItemEnum;
import com.vcredit.creditcat.enumtype.CustIsRealEnum;
import com.vcredit.creditcat.model.AuthItem;
import com.vcredit.creditcat.model.AuthLog;
import com.vcredit.creditcat.model.AuthNetcredit;
import com.vcredit.creditcat.model.Cust;
import com.vcredit.creditcat.service.AuthLogService;
import com.vcredit.creditcat.service.AuthNetcreditService;
import com.vcredit.creditcat.service.CustService;
import com.vcredit.creditcat.util.ConcurrentDateUtil;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.BeanUtil;
import com.vcredit.framework.util.JacksonUtil;

@Service(protocol = { "protocol1" }, version = "1.0")
public class NetCreditManager implements IAuthNetCreditManager {

	@Autowired
	private INetCreditService netCreditService;
	@Autowired
	private AuthNetcreditService authNetcreditService;
	@Autowired
	private CreditCatProcessManager creditCatProcessManager;
	@Autowired
	private AuthLogService authLogService;
	@Autowired
	private CustService custService;

	private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Override
	public InitDto init(Long processId, Long custId) throws Exception {
		BirdResponse init = netCreditService.netInit();
		AuthNetcredit credit = authNetcreditService.findByProcessId(processId);
		if (credit == null) {
			AuthNetcredit auth = new AuthNetcredit(custId, processId, AuthCreditStatusEnum.INIT.getCode(),
					init.getToken());
			authNetcreditService.insert(auth);
		} else {
			AuthNetcredit auth = new AuthNetcredit(credit.getAuthCreditId(), AuthCreditStatusEnum.INIT.getCode(),
					init.getToken());
			if (credit.computeExpire())
				auth.setExpiredTime("");
			authNetcreditService.update(auth);
		}
		InitDto dto = new InitDto();
		if (init != null)
			BeanUtil.copy(init, dto);
		return dto;
	}

	@Override
	public BankcardInitResult bankcardInit(Long custId, BankcardInitDto dto) throws Exception {
		BankcardInitParam param = new BankcardInitParam();
		BeanUtil.copy(dto, param);
		BirdResponse initResult = netCreditService.netBankcardInit(param);
		BankcardInitResult result = new BankcardInitResult();
		BeanUtil.copy(initResult, result);
		result.setStatusCode(initResult.getCode());
		result.setStatusDescription(initResult.getDesc());
		result.setNextProCode(initResult.getNextCode());
		return result;
	}

	@Override
	public NetCreditBaseResultDto bankcardSubmit(Long custId, BankcardSubmitDto dto) throws Exception {
		BankcardSubmitParam param = new BankcardSubmitParam();
		BeanUtil.copy(dto, param);
		BirdResponse result = netCreditService.netBankcardSubmit(param);
		NetCreditBaseResultDto initResult = new NetCreditBaseResultDto();
		BeanUtil.copy(result, initResult);
		initResult.setStatusCode(result.getCode());
		initResult.setStatusDescription(result.getDesc());
		initResult.setNextProCode(result.getNextCode());
		return initResult;
	}

	@Override
	public NetCreditBaseResultDto login(Long processId, Long custId, CreditLoginDto param) throws Exception {
		LoginParam target = new LoginParam();
		BeanUtil.copy(param, target);
		BirdResponse loginResult = netCreditService.netLogin(target);
		AuthNetcredit credit = authNetcreditService.findByProcessId(processId);
		authNetcreditService.update(new AuthNetcredit(credit.getAuthCreditId(), AuthCreditStatusEnum.NORMAL.getCode(),
				loginResult.getToken()));
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(loginResult, dto);
		dto.setStatusCode(loginResult.getCode());
		dto.setStatusDescription(loginResult.getDesc());
		dto.setNextProCode(loginResult.getNextCode());
		return dto;
	}

	@Override
	public NetCreditBaseResultDto getQuestion(QuestionFirstStepDto param) throws Exception {
		QuestionFirstStepParam target = new QuestionFirstStepParam();
		BeanUtil.copy(param, target);
		BirdResponse qustions = netCreditService.netApply1(target);
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(qustions, dto);
		dto.setStatusCode(qustions.getCode());
		dto.setStatusDescription(qustions.getDesc());
		dto.setNextProCode(qustions.getNextCode());
		return dto;
	}

	@Override
	public NetCreditBaseResultDto sumbitAnswer(Long custId, QuestionSecondDto param) throws Exception {
		List<Question> questions = JacksonUtil.Json2Obj(param.getKbaQuestions(), new TypeReference<List<Question>>() {
		});
		QuestionSecondParam target = new QuestionSecondParam(param.getToken(), questions);
		BirdResponse submitAnswer = netCreditService.netApply2(target);
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(submitAnswer, dto);
		dto.setStatusCode(submitAnswer.getCode());
		dto.setStatusDescription(submitAnswer.getDesc());
		dto.setNextProCode(submitAnswer.getNextCode());
		return dto;
	}

	@Override
	public NetCreditBaseResultDto register(RegisterFirstStepDto param) throws Exception {
		RegisterFirstStepParam target = new RegisterFirstStepParam();
		BeanUtil.copy(param, target);
		BirdResponse registerResult = netCreditService.netRegister1(target);

		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(registerResult, dto);
		dto.setStatusCode(registerResult.getCode());
		dto.setStatusDescription(registerResult.getDesc());
		dto.setNextProCode(registerResult.getNextCode());
		return dto;
	}

	@Override
	public NetCreditBaseResultDto registerVerifyMobile(Long custId, RegisterSecondStepDto param) throws Exception {
		RegisterSecondStepParam target = new RegisterSecondStepParam();
		BeanUtil.copy(param, target);
		BirdResponse registerResult = netCreditService.netRegister2(target);
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(registerResult, dto);
		dto.setStatusCode(registerResult.getCode());
		dto.setStatusDescription(registerResult.getDesc());
		dto.setNextProCode(registerResult.getNextCode());
		return dto;
	}

	@Override
	public NetCreditBaseResultDto registerSubmit(RegisterThirdStepDto param) throws Exception {
		RegisterThirdStepParam target = new RegisterThirdStepParam();
		BeanUtil.copy(param, target);
		BirdResponse registerResult = netCreditService.netRegister3(target);
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(registerResult, dto);
		dto.setStatusCode(registerResult.getCode());
		dto.setStatusDescription(registerResult.getDesc());
		dto.setNextProCode(registerResult.getNextCode());
		return dto;
	}

	@Override
	public String summary(Long custId) throws Exception {
		return null;
	}

	@Override
	@Log
	public NetCreditBaseResultDto summaryReport(Long processId, Long custId, ReportDto input) throws Exception {
		ReportParam param = new ReportParam();
//		Cust cust = custService.findById(custId);		
		BeanUtil.copy(input, param);
		BirdResponse result = netCreditService.netReport(param);
		AuthNetcredit credit = authNetcreditService.findByProcessId(processId);
		if (result.getCode() == 0) {// 获取报告成功
//			if(CommonUtil.certNoCompare(cust.getCustIdno(), result.getCertNo()) && cust.getCustName().equals(result.getName())){
				AuthNetcredit auth = new AuthNetcredit(credit.getAuthCreditId(), AuthCreditStatusEnum.SUCCESS.getCode(),
						ConcurrentDateUtil.formatDateTime(ConcurrentDateUtil.getVirguleDate(result.getEndTime())), result.getCertNo(),
						result.getCreditId() == null ? null : result.getCreditId().toString(), result.getReportSn(),
						ConcurrentDateUtil.format(new Date()), CustIsRealEnum.Yes.getCode());
				auth.setExpiredTime(ConcurrentDateUtil.formatDateTime(ConcurrentDateUtil.addDayTime(new Date(), 30)));
				updateItem(auth, processId, custId, AuthItemEnum.BANK_CREDIT);
//			}else{
//				throw new Exception("检测到使用非本人的账号登录，请退出后，使用本人的征信登录名登录！");
//			}
		}
		NetCreditBaseResultDto dto = new NetCreditBaseResultDto();
		BeanUtil.copy(result, dto);
		dto.setStatusCode(result.getCode());
		dto.setStatusDescription(result.getDesc());
		dto.setNextProCode(result.getNextCode());
		return dto;
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	private void updateItem(AuthNetcredit auth, Long processId, Long custId, AuthItemEnum authEnum) throws Exception {
		authNetcreditService.update(auth);
		creditCatProcessManager.itemDone(new AuthItem(authEnum.getCode()), processId);
		authLogService.insert(new AuthLog(processId, custId, authEnum.getCode(), auth.getExpiredTime(), new Date()));
	}

	@Override
	public String applyResult(Long custId) throws Exception {
		return null;
	}

	@Override
	public ReportResponseDto reportAll(Long processId, Long custId) throws Exception {
		AuthNetcredit credit = authNetcreditService.findByProcessId(processId);
		if (null == credit) {
			throw new Exception("没有走征信认证,请走完征信认证，才能看到征信报告哦！");
		}
		Cust cust = custService.findById(custId);
		//if (!StringUtils.isEmpty(cust.getCustIdno())) {
			BirdResponse result = netCreditService.reportAll(new ReportAllParam("", credit.getReportSn(), ""));

			BaseInfoDto baseInfo = new BaseInfoDto(result.getName(), result.getMaritalState(), result.getCertNo(),
					format.parse(result.getReportCreateTime()).getTime());

			CardRecordDto cardRecord = covertCardRecord(result.getCrdCdLndList());
			LoanRecordDto loanRecord = covertLoanRecord(result.getCrdCdLnlist());
			QueryRecordDto queryRecord = covertQueryRecord(result.getCrdQrRecorddtLList());
			return new ReportResponseDto(baseInfo, cardRecord, loanRecord, null, queryRecord);
		//}
		//return null;

	}

	private QueryRecordDto covertQueryRecord(List<CreditRecordResultParam> param) throws ParseException {
		List<QuerySerialDto> overdueList = new ArrayList<QuerySerialDto>();
		List<QuerySerialDto> nooverdueList = new ArrayList<QuerySerialDto>();
		for (CreditRecordResultParam creditCard : param) {
			if (NetCreditQufierEnum.ONESELF.getDesc().equals(creditCard.getQuerier())) {// 本人
				nooverdueList.add(new QuerySerialDto(creditCard.getId().toString(),
						format.parse(creditCard.getQueryDate()).getTime(), creditCard.getQuerier(),
						creditCard.getQueryReason()));
			} else {// 机构
				overdueList.add(new QuerySerialDto(creditCard.getId().toString(),
						format.parse(creditCard.getQueryDate()).getTime(), creditCard.getQuerier(),
						creditCard.getQueryReason()));
			}
		}
		return new QueryRecordDto(String.valueOf(overdueList.size()), String.valueOf(nooverdueList.size()),
				new QueryRecordsDetail(overdueList, nooverdueList));
	}

	private CardRecordDto covertCardRecord(List<CreditCardResultParam> param) {
		List<CardSerialDto> overdueList = new ArrayList<CardSerialDto>();
		List<CardSerialDto> nooverdueList = new ArrayList<CardSerialDto>();
		List<CardSerialDto> overdue90List = new ArrayList<CardSerialDto>();
		for (CreditCardResultParam creditCard : param) {
			if (creditCard.getOverdueCyc() == 0 && creditCard.getOverdueOver90Cyc() == 0) {// 不逾期
				nooverdueList.add(new CardSerialDto(creditCard.getFinanceOrg() + "(" + creditCard.getCurrency() + ")",
						creditCard.getCreditLimitAmount().longValue(),
						creditCard.getUsedCreditLimitAmount() == null ? 0
								: creditCard.getUsedCreditLimitAmount().longValue(),
						creditCard.getOverdueCyc(), creditCard.getOverdueOver90Cyc(), 0));
			} else if (creditCard.getOverdueOver90Cyc() > 0) {
				overdue90List.add(new CardSerialDto(creditCard.getFinanceOrg() + "(" + creditCard.getCurrency() + ")",
						creditCard.getCreditLimitAmount().longValue(),
						creditCard.getUsedCreditLimitAmount().longValue(), creditCard.getOverdueCyc(),
						creditCard.getOverdueOver90Cyc(), 1));
			} else {
				overdueList.add(new CardSerialDto(creditCard.getFinanceOrg() + "(" + creditCard.getCurrency() + ")",
						creditCard.getCreditLimitAmount().longValue(),
						creditCard.getUsedCreditLimitAmount().longValue(), creditCard.getOverdueCyc(),
						creditCard.getOverdueOver90Cyc(), 1));
			}
		}
		return new CardRecordDto(String.valueOf(param.size()), String.valueOf(nooverdueList.size()),
				String.valueOf(overdueList.size()), String.valueOf(overdue90List.size()),
				new CardRecordsDetail(overdueList, nooverdueList));
	}

	private LoanRecordDto covertLoanRecord(List<CreditLoanResultParam> param) {
		List<LoanRecordDetailDto> overdueList = new ArrayList<LoanRecordDetailDto>();
		List<LoanRecordDetailDto> nooverdueList = new ArrayList<LoanRecordDetailDto>();
		List<LoanRecordDetailDto> overdue90List = new ArrayList<LoanRecordDetailDto>();
		for (CreditLoanResultParam loanResult : param) {
			if (loanResult.getOverdueCyc() == 0 && loanResult.getOverdueOver90Cyc() == 0) {// 不逾期
				nooverdueList
						.add(new LoanRecordDetailDto(loanResult.getFinanceOrg() + "(" + loanResult.getCurrency() + ")",
								loanResult.getTypeDw(), loanResult.getCreditLimitAmount().longValue(),
								loanResult.getBalance() == null ? 0 : loanResult.getBalance().longValue(), false,
								loanResult.getOverdueCyc(), loanResult.getOverdueOver90Cyc()));
			} else if (loanResult.getOverdueOver90Cyc() > 0) {
				overdue90List
						.add(new LoanRecordDetailDto(loanResult.getFinanceOrg() + "(" + loanResult.getCurrency() + ")",
								loanResult.getTypeDw(), loanResult.getCreditLimitAmount().longValue(),
								loanResult.getBalance() == null ? 0 : loanResult.getBalance().longValue(), true,
								loanResult.getOverdueCyc(), loanResult.getOverdueOver90Cyc()));
			} else {
				overdueList
						.add(new LoanRecordDetailDto(loanResult.getFinanceOrg() + "(" + loanResult.getCurrency() + ")",
								loanResult.getTypeDw(), loanResult.getCreditLimitAmount().longValue(),
								loanResult.getBalance() == null ? 0 : loanResult.getBalance().longValue(), true,
								loanResult.getOverdueCyc(), loanResult.getOverdueOver90Cyc()));
			}
		}
		return new LoanRecordDto(String.valueOf(param.size()), String.valueOf(nooverdueList.size()),
				String.valueOf(overdueList.size()), String.valueOf(overdue90List.size()),
				new LoanRecordsDto(overdueList, nooverdueList));
	}

	@Override
	public void sendReport(Long processId, Long custId, String email) throws Exception {
		Cust cust = custService.findById(custId);
		if (cust == null) {
			throw new Exception("客户不存在！");
		}
		AuthNetcredit authNet = authNetcreditService.findByProcessId(processId);
		if (authNet == null || AuthCreditStatusEnum.SUCCESS.getCode() != authNet.getCreditStatus()) {
			throw new Exception("征信还没有认证！请重新认证！");
		}
		netCreditService.netSendReport(new EmailParam(email, "", cust.getCustName(), authNet.getReportSn()));
	}

}
